/**
 * User: alesj
 * Date: 2005.6.6
 * Time: 11:28:49
 * 
 * (C) Genera Lynx d.o.o.
 */

package com.alesj.newsfeed.web.form;

import java.text.DateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.mail.internet.InternetAddress;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.alesj.newsfeed.data.Account;
import com.alesj.newsfeed.data.Contact;
import com.alesj.newsfeed.data.Message;
import com.alesj.newsfeed.web.object.SearchCommand;
import com.generalynx.common.constants.WebConst;
import com.generalynx.ecos.data.User;
import com.generalynx.ecos.utils.BeanConst;
import org.springframework.beans.propertyeditors.CustomDateEditor;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.validation.BindException;
import org.springframework.web.bind.RequestUtils;
import org.springframework.web.bind.ServletRequestDataBinder;
import org.springframework.web.servlet.ModelAndView;

public class SearchForm extends ExecutorHolderController {

    private String selectView;

    public SearchForm() {
        setCommandClass(SearchCommand.class);
    }

    protected ModelAndView showForm(HttpServletRequest request,
                                    HttpServletResponse response,
                                    BindException errors) throws Exception {
        int messageId = RequestUtils.getIntParameter(request, "messageId", 0);
        if (messageId > 0) {
            Message message = getBasicDAO().loadMessage(messageId);
            Boolean resubmit = RequestUtils.getBooleanParameter(request, "resubmit");
            if (resubmit != null && resubmit) {
                User creator = (User)request.getSession(false).getAttribute(WebConst.USER);
                getBasicDAO().initialize(message);
                getBasicDAO().initialize(message.getAccount());
                getBasicDAO().initialize(message.getFailed());
                Sender sender = new Sender(message, creator);
                taskExecutor.execute(sender);
                return new ModelAndView("msgView", WebConst.MSG_CODE, "resubmitted");
            } else {
                return getMessageView(message);
            }
        } else {
            return super.showForm(request, response, errors);
        }
    }

    protected Map referenceData(HttpServletRequest request) throws Exception {
        Map<String, Object> model = new HashMap<String, Object>();
        model.put("creators", getBasicDAO().findUsers());
        return model;
    }

    protected void initBinder(HttpServletRequest request, ServletRequestDataBinder binder)
            throws Exception {
        super.initBinder(request, binder);
        DateFormat df = (DateFormat) getApplicationContext().getBean(BeanConst.DEFAULT_DATE_FORMAT);
        binder.registerCustomEditor(Date.class, new CustomDateEditor(df, true));
    }

    protected ModelAndView onSubmit(HttpServletRequest request,
                                    HttpServletResponse response,
                                    Object command,
                                    BindException errors) throws Exception {

        SearchCommand sc = (SearchCommand) command;
        User creator = (sc.getCreatorId() > 0) ? getBasicDAO().loadUser(sc.getCreatorId()) : null;
        List messages = getBasicDAO().findMessages(
                sc.getSubject(),
                sc.getFrom(),
                sc.getTill(),
                creator,
                sc.getFailed());
        if (messages.size() > 1) {
            return new ModelAndView(getSelectView(), "messages", messages);
        } else if (messages.isEmpty()) {
            return new ModelAndView("msgView", WebConst.MSG_CODE, "empty_messages");
        } else {
            return getMessageView((Message) messages.get(0));
        }
    }

    private ModelAndView getMessageView(Message message) {
        return new ModelAndView(getSuccessView(), "message", message);
    }

    /* setters && getters */

    public String getSelectView() {
        return selectView;
    }

    public void setSelectView(String selectView) {
        this.selectView = selectView;
    }

    private class Sender implements Runnable {

        private Message oldMessage;
        private Message newMessage;

        public Sender(Message message, User creator) {
            this.oldMessage = message;
            this.newMessage = (Message) message.clone();
            this.newMessage.setCreator(creator);
        }

        public void run() {
            try {
                logger.info("Resubmitting message " + oldMessage + ".");
                Account account = newMessage.getAccount();
                MimeMessageHelper helper = new MimeMessageHelper(getMailClient().createMimeMessage(), true, encoding);
                helper.setFrom(account.getEmail(), account.getName());
                helper.setSubject(newMessage.getSubject());
                helper.setText(newMessage.getContent(), newMessage.isHtml());
                if (oldMessage.getAttachments() > 0) {
                    addAttachments(helper, attachmentHandler.getAttachments(String.valueOf(oldMessage.getId())));    
                }
                Set<Contact> failed = oldMessage.getFailed();
                logger.info("Resubmitting to failed contacts, size: " + failed.size());
                Set<Contact> nrec = new HashSet<Contact>();
                Set<Contact> nfail = new HashSet<Contact>();
                for (Contact contact : failed) {
                    sendMessage(helper, contact, nrec, nfail);
                }
                newMessage.setRecepients(nrec);
                newMessage.setFailed(nfail);
                getBasicDAO().saveOrUpdateEntity(newMessage);
            } catch (Throwable t) {
                logger.error("Failed to resubmit: " + t);
            } finally {
                sendReport(newMessage);    
            }
        }

        private void sendMessage(MimeMessageHelper helper, Contact contact, Set<Contact> r, Set<Contact> f) throws Exception {
            try {
                helper.setTo(new InternetAddress(contact.getEmail(), contact.getLabel()));
                getMailClient().sendMail(helper.getMimeMessage());
                r.add(contact);
            } catch (Throwable t) {
                logger.warn("Unable to resubmit message " + newMessage + " for contact: " + contact + ", " + t);
                f.add(contact);
            }
        }

    }
}
